用蒙特卡洛和BS分别模拟股价波动并分析对应期权价格波动和对冲策略表现(python)

您所在的位置:网站首页 r语言monte carlo模拟 用蒙特卡洛和BS分别模拟股价波动并分析对应期权价格波动和对冲策略表现(python)

用蒙特卡洛和BS分别模拟股价波动并分析对应期权价格波动和对冲策略表现(python)

2023-07-27 05:13| 来源: 网络整理| 查看: 265

大三的一个大作业,时间有点久远,这里把代码块和解释都尽量补齐,毕竟是耗费两个月的作品还是有感情。我用的是 jupyter notebook, 先下一个 Anaconda 就可以,以后要用的时候就终端输入 jupyter notebook 就能自动跳转页面

首先 task 是

dS/S = r*dt + sigma*dW dB/B = r*dt a.1) Simulate S with MC reduction methods a.2) Simulate European option price with MC and BS model b. Conduct performance analysis by changing M and N c. Estimate the probability functions of strike price d) implement static delta-neutral strategy in MC e) implement static delta-gamma-neutral strategy in MC

随机过程的公式就是上面的 dS/S,股价随机波动,当然具体的sigma,r 等参数后面是自己设定的

这里用人话解释一下是什么意思(中外合办大学,英文教学两行泪) a1 首先用蒙特卡洛的 reduction 方法模拟出股票也就是 Stock 的价格变化 a2 然后 MC 和 BS 的方法算出欧洲期权的实时价格,也就是一个分离和连续时间的区别,这里用一下公式就行了 b 通过交换 M 和 N(M 是有几种股价 jump 的方向,N 是进行多少个周期也就是 steps),来监测股价波动的表现 c 画出 strike price(K)的概率图 d 用 monte-carlo 方法实施静态 delta 中性对冲策略 e 用 monte-carlo 方法实施静态 delta-gamma 中性对冲策略

首先调包 numpy, pandas, matplotlib 基本操作,防止后面出现一些奇怪的报错

import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.stats import norm

然后是一些函数定义,之后要用到就直接拿来用了

def EulerMilsteinMCStock(scheme, parameters): np.random.seed(1000) # time setup T = parameters['setup']['T'] # total time/maturity numSteps = parameters['setup']['numSteps'] # number of steps numPaths = parameters['setup']['numPaths'] # number of simulated paths dt = parameters['setup']['dt'] # model parameters S_0 = parameters['model']['S0'] # initial value sigma = parameters['model']['sigma'] # initial value rf = parameters['model']['rf'] # initial value # simulation S = np.zeros((numSteps + 1, numPaths),dtype=float) S[0,:] = np.log(S_0) ################ simluations for asset price S ######## for i in range(numPaths): for t_step in range(1, numSteps+1): # the 2 stochastic drivers for variance V and asset price S and correlated Zs = np.random.normal(0, 1, 1) if scheme == 'Euler': S[t_step,i] = S[t_step-1,i] + (rf-sigma**2/2)*dt + sigma*np.sqrt(dt)*Zs elif scheme == 'Milstein': # Euler and Milstein have the same discretization scheme for Log(S) due to dsigma(t,X)/dX =0 S[t_step,i] = S[t_step-1,i] + (rf-sigma**2/2)*dt + sigma*np.sqrt(dt)*Zs return np.exp(S)

这个 Euler 和 Milstein 是两种 MC simulation 的方法,各有利弊和简便之分,这个我们一般用 Euler 就可以了。np.random.seed() 是随机生成种子数,了解蒙特卡洛原理的就知道这个本身就是要很多次实验下产生的结果更加准确,你想要一亿两亿都可以。

然后是time的设定,总时间,总步数(N),还有一次jump的路径数量(M),dt 就是 T/N

model 的参数设定,Stock 初始价格,波动参数,无风险利率,都是后面自己设定的,不要太夸张给个2%就行。

然后就是算法原理的代码实践。输出股价和时间的对应。

第二个函数定义,BS model,这个公式是量化金融常出现的。用来测算期权价格应用很广泛,定义之后就可以直接用了。

def Black_ScholesPrice(parameters): S0 = parameters['model']['S0'] sigma = parameters['model']['sigma'] K = parameters['asset']['K'] rf = parameters['model']['rf'] T = parameters['setup']['T'] option_type = parameters['asset']['optype'] DF = np.exp(-rf*T) d1 = (np.log(S0/K)+(rf+0.5*sigma**2)*T)/(sigma*np.sqrt(T)) d2 = d1 - sigma * np.sqrt(T) if option_type == 1: # call option_price = S0 * norm.cdf(d1) - K * DF * norm.cdf(d2) elif option_type == -1: # put option_price = K * DF * norm.cdf(-d2) - S0 * norm.cdf(-d1) return option_price

至此,我们就可以做 a1 a2 小题了,因为公式都定义好了,之后用 main 环境就可以直接运行。定义一下参数们,用一下之前定义好的函数。这个等会再一起和对冲码出来。

接下来就是 b 的要求,变化 M 和 N 的数值,看一下股价的表现,在不同方法的模拟下,这一块由于我们的电脑实在带不动大的 M 和 N,你想 M=10000 就意思是一个价格在某一时刻有 10000 种上升或下降的不同价格,配上一个大 N,我的破 Mac 根本带不动,于是我们用小的数据慢慢的一个个试,从 M=200,N=200 开始,一直到 M=5000, N=200, 我们发现其实 N 太大了会影响作图的清晰度所以我们就保持在200 就刚刚好,M 上了千之后其实目测的效果都是差不多的,大概在 50-200,的价格波动(初始价格 S0 =100),头铁的话可以试试建个数组让 M 和 N 分别变化看 performance,我们的小电脑一下就卡死了。形而上学,看看就好:

M = np.arange(2000,50000,2000) Option_Price = np.zeros(len(M)) BS_line = np.empty(len(M)) for i in range(len(M)): BS_line[i] = BS_price #print(BS_line) for i in range(0,len(M)): M_new=M[i] parameters = {'model':{'S0':S0, 'sigma':sigma, 'rf':rf}, 'asset':{'K':K, 'optype': Optype}, 'setup':{'T':T, 'numSteps':N, 'dt': T/N, 'numPaths':M_new} } Sim_S = EulerMilsteinMCStock('Euler', parameters) S_T = Sim_S[-1,:] Option_Price[i] = MC_option_price(S_T, parameters) #print(Option_Price) plt.figure(figsize=(12,8)) plt.plot(M,Option_Price) plt.plot(M,BS_line) plt.ylabel('Monte Carlo Option Price') plt.xlabel('Number of Paths') plt.show() N = np.arange(500,44500,2000) Option_Price_1 = np.zeros(len(N)) #print(N) BS_line = np.empty(len(N)) for i in range(len(N)): BS_line[i] = BS_price #print(BS_line) for i in range(0,len(N)): N_new=N[i] parameters = {'model':{'S0':S0, 'sigma':sigma, 'rf':rf}, 'asset':{'K':K, 'optype': Optype}, 'setup':{'T':T, 'numSteps':N_new, 'dt': T/N_new, 'numPaths':M} } Sim_S = EulerMilsteinMCStock('Euler', parameters) S_T = Sim_S[-1,:] Option_Price_1[i] = MC_option_price(S_T, parameters) #print(Option_Price_1) plt.figure(figsize=(12,8)) plt.plot(N,Option_Price_1) plt.plot(N,BS_line) plt.ylabel('Monte Carlo Option Price') plt.xlabel('Number of time steps') plt.show()

这块其实不是那么重要,因为大家都跑不出来,你有理说一个你觉得好的 M 和 N 就可以了,毕竟咱们也没那么好的电脑是不是。 其实到这 b 就解决了,出来一个像 K 线一样的图。

股价波动图 N=300

这里我们用了一个很小的 N 就是因为发现大了之后图真看不清了,还不如小点清晰度高,反正之前都验证过了大点小点没什么特别大的关系,有关系我们也看不出来,也要对应大交易量才能看出来。

那 c 的话就是求一个 St=K 的概率, call option 的话当你 St>K 那肯定就要成交了,所以我们在这个地方需要用到 call option 的公式,经过一系列的数学推导(提示,option price 的公式中有用到期望值,期望值可以用积分代替,这样就可以转化成某个区域的 probability),代码如下:

#estimate cumulative/density function K_set = np.arange(150,50,-0.5, float) num_K = len(K_set) MC_price_Ks = np.zeros(num_K) for i in range(num_K): parameters['asset']['K'] = K_set[i] MC_price_Ks[i] = MC_option_price(S_T, parameters) # convert into dataframe MC_K_vs_price = pd.DataFrame(np.transpose([K_set,MC_price_Ks]), index =list(range(0, num_K)), columns=['K', 'Price']) #print(MC_K_vs_price) # estimate culumative probs HigherThanK_prob = ProbHigherThanK(K_set, MC_price_Ks, parameters) # estimate density probs den_probs = Density_prob(K_set, MC_price_Ks, parameters) # save all data All_info = pd.DataFrame(np.transpose([K_set,MC_price_Ks, HigherThanK_prob, den_probs]), index =list(range(0, num_K)), columns=['K', 'Price', 'Prob(ST>K)', 'Prob(ST=K)']) # print(All_info) All_info.to_excel(r"all_MC_info.xlsx") # plot plt.figure(figsize=(60,45)) plt.subplot(1,3,1) plt.plot(K_set, den_probs, 'b') plt.grid(True) plt.xlabel('K') plt.ylabel('Prob(ST=K)') plt.subplot(1,3,2) plt.plot(K_set, HigherThanK_prob, 'b') plt.grid(True) plt.xlabel('K') plt.ylabel('Prob(ST>K)') plt.subplot(1,3,3) plt.plot(K_set, 1-HigherThanK_prob, 'b') plt.grid(True) plt.xlabel('K') plt.ylabel('Prob(ST


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3